// 存储 localStorage
export const setStore = (name, content) => {
	if(!name) return;
	if(typeof content !== 'string'){
		content = JSON.stringify(content);
	}
	window.localStorage.setItem(name, content)
}

// 获取localStorage
export const getStore = name => {
	if(!name) return;
	return window.localStorage.getItem(name);
}

// 删除localStorage
export const removeStore = name => {
	if(!name) return;
	window.localStorage.removeItem(name);
}

// 获取style样式
export const getStyle = (element, attr, NumberMode = 'int') => {
	// var NumberMode=arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'int';
	let target;
	if (attr === 'scrollTop'){		// scrollTop 获取方式不同
		target = element.scrollTop;
	}else if(element.currentStyle){		// IE
		target = element.currentStyle[attr];
	}else{								// 其他浏览器  返回一个CSS样式对象。
		target = document.defaultView.getComputedStyle(element,null)[attr];
	}
	// 获取 opacity 需要取小数
	return NumberMode == 'float' ? parseFloat(target) : parseInt(target);
}

// 页面到达底部 加载更多
export const loadMore = (element, callback) => {
	// 取用户电脑屏幕的高度，不关浏览器或者顶部工具栏跟底部工具栏的高度
	let windowHeight = window.screen.height;
	let height;
	let setTop;
	let paddingBottom;
	let marginBottom;
	let requestFram;
	let oldScrollTop;
	
	document.body.addEventListener('scroll',() => {
		loadMore();
	},false)		// 默认false

	// 运动开始时获取元素的 [手指触摸屏幕时候触发]
	// passive 监听器能保证是调用 preventDefault() 无效 
	element.addEventListener('touchstart',() => {			
		height = element.offsetHeight;						// 元素的高度包括边框和填充，但不是边距
		setTop = element.offsetTop;							// 当前对象到其上级层顶部的距离
		paddingBottom = getStyle(element, 'paddingBottom');
		marginBottom = getStyle(element, 'marginBottom');
	},{passive: true})

	// 运动过程中保持监听 scrollTop 值判断是否到达顶部
	element.addEventListener('touchmove',() => {
		loadMore();
	},{passive: true})

	// 运动结束判断是否有惯性运动 惯性运动结束后判断是否到底底部
	element.addEventListener('touchend',() => {
		oldScrollTop = document.body.scrollTop;
		moveEnd();
	},{passive: true})

	const moveEnd = () => {
		requestFram = requestAnimationFrame(() => {
			if(document.body.scrollTop != oldScrollTop){
				oldScrollTop = document.body.scrollTop;
				loadMore();
				moveEnd();
			}else{
				cancelAnimationFrame(requestFram);
				// 防止鼠标抬起时已经渲染好数据导致重新获取数据  应该重新获取dom高度
				height = element.offsetHeight;
				loadMore();
			}
		})
	}
	const loadMore = () => {
		// 当前页面滚动条的位置 + 电脑屏幕高度 大于等于 
		if(document.body.scrollTop + windowHeight >= height + setTop + paddingBottom + marginBottom){
			callback();
		}
	}
}

// 显示返回顶部的按钮 开始，结束，运动 三个过程中调用函数判断是否达到目标点
export const showBack = callback => {
	let requestFram;
	let oldScrollTop;

	document.addEventListener('scroll',() => {
		showBackFun();
	}, false);
	document.addEventListener('touchstart',() => {
		showBackFun();
	},{passive: true});
	document.addEventListener('touchmove',() => {
       showBackFun();
    },{passive: true})
    document.addEventListener('touchend',() => {
        oldScrollTop = document.body.scrollTop;
        moveEnd();
    },{passive: true});

    const moveEnd = () => {
    	// 若您想要在下次重绘时产生另一个动画画面，您的回调例程必须调用 
    	requestFram = requestAnimationFrame(() => {
    		if(document.body.scrollTop != oldScrollTop){
    			oldScrollTop = document.body.scrollTop;
    			moveEnd();
    		}else{
    			// 取消一个先前通过调用window.requestAnimationFrame()方法添加到计划中的动画帧请求
    			cancelAnimationFrame(requestFram);
    		}
    		showBackFun();
    	})
    }
	// 判断是否达到目标点
	const showBackFun = () => {
		if(document.body.scrollTop > 500){
			callback(true);
		}else{
			callback(false);
		}
	}
}

/**
 * 运动效果
 * @param {HTMLElement} element   运动对象，必选
 * @param {JSON}        target    属性：目标值，必选
 * @param {number}      duration  运动时间，可选
 * @param {string}      mode      运动模式，可选
 * @param {function}    callback  可选，回调函数，链式动画
 */
// ease-out 慢速结束 
export const animate = (element, target, duration=400, mode='ease-out', callback) => {
	clearInterval(element.timer);
	// 判断不同参数的情况
	if(duration instanceof Function){
		callback = duration;
		duration = 400;
	}else if(duration instanceof String){
		mode = duration;
		duration = 400;
	}
	if(mode instanceof Function){
		callback = mode;
		mode = 'ease-out';
	}
	// 获取dom样式
	const attrStyle = attr => {
		if(attr === 'opacity'){
			// 获取元素的透明度 进行四舍五入
			return Math.round(getStyle(element, attr, 'float') * 100);
		}else{
			return getStyle(element, attr);
		}
	}
	// 根字体大小 需要将rem 改成px加絮凝运算
	const rootSize = parseFloat(document.documentElement.style.fontSize);
	const unit = {};
	const initState = {};
	// 获取目标属性单位和初始样式值
	Object.keys(target).forEach(attr => {
		if (/[^\d^\.]+/gi.test(target[attr])) {
            unit[attr] = target[attr].match(/[^\d^\.]+/gi)[0] || 'px';
        }else{
            unit[attr] = 'px';
        }
        initState[attr] = attrStyle(attr);
	});
	//去掉传入的后缀单位
    Object.keys(target).forEach(attr => {
        if (unit[attr] == 'rem') {
            target[attr] = Math.ceil(parseInt(target[attr])*rootSize);
        }else{
            target[attr] = parseInt(target[attr]);
        }
    });

	let flag = true;				// 假设所有运动到达终点
	const remberSpeed = {};			// 记录上一个速度值，在ease-in模式下需要用到
	element.timer = setInterval(() => {
		Object.keys(target).forEach(attr => {
			let iSpeed = 0;			// 步长
			let status = false;		// 是否仍需运动
			let iCurrent = attrStyle(attr) || 0;		// 当前元素属性值
			let speedBase = 0;		// 目标点需要减去的基础值，三种运动状态的值都不同
            let intervalTime; 		//将目标值分为多少步执行，数值越大，步长越小，运动时间越长
             switch(mode){
                case 'ease-out': 
                    speedBase = iCurrent;
                    intervalTime = duration*5/400;
                    break;
                case 'linear':
                    speedBase = initState[attr];
                    intervalTime = duration*20/400;
                    break;
                case 'ease-in':
                    let oldspeed = remberSpeed[attr] || 0;
                    iSpeed = oldspeed + (target[attr] - initState[attr])/duration;
                    remberSpeed[attr] = iSpeed
                    break;
                default:
                    speedBase = iCurrent;
                    intervalTime = duration*5/400; 
            };
            if (mode !== 'ease-in') {
                iSpeed = (target[attr] - speedBase) / intervalTime;
                iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
            }
            //判断是否达步长之内的误差距离，如果到达说明到达目标点
            switch(mode){
                case 'ease-out': 
                    status = iCurrent != target[attr]; 
                    break;
                case 'linear':
                    status = Math.abs(Math.abs(iCurrent) - Math.abs(target[attr])) > Math.abs(iSpeed);
                    break;
                case 'ease-in':
                    status = Math.abs(Math.abs(iCurrent) - Math.abs(target[attr])) > Math.abs(iSpeed);
                    break;
                default:
                    status = iCurrent != target[attr]; 
            };
            if (status) {
                flag = false; 
                //opacity 和 scrollTop 需要特殊处理
                if (attr === "opacity") {
                    element.style.filter = "alpha(opacity:" + (iCurrent + iSpeed) + ")";
                    element.style.opacity = (iCurrent + iSpeed) / 100;
                } else if (attr === 'scrollTop') {
                    element.scrollTop = iCurrent + iSpeed;
                }else{
                    element.style[attr] = iCurrent + iSpeed + 'px';
                }
            } else {
                flag = true;
            }

            if (flag) {
            	// 运动到达终点  清除定时器
                clearInterval(element.timer);
                if (callback) {
                    callback();
                }
            }
		})
	}, 20);
}